package com.dm.framework.v2.servlet;


import com.dm.framework.v2.annotation.DMController;
import com.dm.framework.v2.annotation.DMService;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import static java.lang.System.*;

/**
 * Created by xiaodao
 * date: 2019/12/13
 * com.dm.framework.v2.servlet.DMDispatcherServlet
 */
public class DMDispatcherServlet extends HttpServlet {

    private Properties contextConfig = new Properties();
    //保存所有扫描到的类名
    private List<String> classNames = new ArrayList<>();
    /**
     * 实例化的ioc容器
     */
    private Map<String, Object> ioc = new LinkedHashMap<>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //运行阶段.
        doDispatcher(req, resp);

    }

    private void doDispatcher(HttpServletRequest req, HttpServletResponse resp) {
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        //1 loan config
        doLoadConfig(config.getInitParameter("contextConfigLocation"));
        //2 scan 相关的类
        doScanner(contextConfig.getProperty("scanpackage"));
        //3.初始化扫描到的类,并且讲他们放入到IOC容器中
        doInstance();
        //4 完成依赖注入

        doAutowired();
        //5. 初始化handlerMapping
        initHanlderMapping();

        System.out.println("dm spring framework init ");
    }

    private void initHanlderMapping() {
    }

    private void doAutowired() {
    }

    private void doInstance() {
        if (classNames.isEmpty()) {
            return;
        }
        try {
            for (String className : classNames) {
                Class<?> clazz = Class.forName(className);
                //加了注解的类才需要初始化->反射 ,接口不需要初始化
                //为了简化代码逻辑.体会设计 没有@componment
                if (clazz.isAnnotationPresent(DMController.class) || clazz.isAnnotationPresent(DMService.class)) {
                    Object instance = clazz.newInstance();
                    //首字母小写
                    String beanName = instance.getClass().getSimpleName();
                    ioc.put(instance.getClass().getSimpleName(), instance);
                } else if (clazz.isAnnotationPresent(DMService.class)) {
                    //1.默认类名 首字母小写
                    //自定义类名 beanName
                    //3.根据类型自动赋值
                    DMService service = clazz.getAnnotation(DMService.class);
                    String beanName = service.value();
                    if ("".equals(beanName.trim())) {//如果没有自定义名字就取默认值
                    beanName = toLowerirstCase(clazz.getSimpleName());

                    }
                    //3.根据类名自动赋值.
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private String toLowerirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        //大小写ASCII相差32
        //大写的比小写的ascii 码小
        chars[0] += 32;
        return String.valueOf(chars);
    }

    /**
     * 扫描相关的类
     *
     * @param scanpackage
     */
    private void doScanner(String scanpackage) {
        //com.dm.framework 包路劲 转换为文件路径.
        //classpath
        URL url = this.getClass().getClassLoader().getResource("/" + scanpackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());

        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScanner(scanpackage + "." + file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    continue;
                }
                String className = scanpackage + "." + file.getName().replace(".class", "");
                classNames.add(className);


            }
        }
    }

    /**
     * 加载配置文件
     *
     * @param contextConfigLocation
     */
    private void doLoadConfig(String contextConfigLocation) {

        InputStream in = null;
        //从类路劲找到spring的主配置文件.读取出来
        in = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
